package com.redoor.app.stake.basicdata.service.impl;

import com.redoor.app.stake.auth.commons.DatabaseServiceStatus;
import com.redoor.app.stake.auth.service.BaseUserService;
import com.redoor.app.stake.basicdata.commons.BasicDataStatus;
import com.redoor.app.stake.basicdata.dao.BaseStakeExtendInfoMapper;
import com.redoor.app.stake.basicdata.dao.BaseStakeMapper;
import com.redoor.app.stake.basicdata.model.*;
import com.redoor.app.stake.basicdata.model.constants.BasicDataRedisConstants;
import com.redoor.app.stake.basicdata.model.controllerModel.BaseChargerModifyBean;
import com.redoor.app.stake.basicdata.model.controllerModel.BaseStakeCriteria;
import com.redoor.app.stake.basicdata.model.controllerModel.BaseStakeModifyBean;
import com.redoor.app.stake.basicdata.model.serviceModel.BaseStakeServiceBean;
import com.redoor.app.stake.basicdata.mq.sendService.impl.SendMQServiceImpl;
import com.redoor.app.stake.basicdata.service.*;
import com.redoor.app.stake.common.utils.UUIDTool;
import com.redoornetwork.framework.core.exception.ServiceException;
import com.redoornetwork.framework.mybatis.service.AbstractService;
import com.yotouch.app.stake.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by wangjunlei on 2018-02-12 10:08:10.
 */
@Service
@Transactional
public class BaseStakeServiceImpl extends AbstractService<BaseStake, String> implements BaseStakeService {

    private Logger logger = LoggerFactory.getLogger(BaseStakeServiceImpl.class);

    /**
     * 注入持久层
     */
    @Autowired
    private BaseStakeMapper baseStakeMapper;

    @Autowired
    private BaseStakeRedisService baseStakeRedisService;

    @Autowired
    private SendMQServiceImpl mqService;

    @Autowired
    private BaseSystemOperationLogService baseSystemOperationLogService;

    @Autowired
    private BaseAssetOperationTrajectoryService baseAssetOperationTrajectoryService;

    @Autowired
    private BaseChargerService baseChargerService;

    @Autowired
    private BaseParkingSpaceService baseParkingSpaceService;

    @Autowired
    private BaseStationService baseStationService;

    @Autowired
    private BaseStakeExtendInfoMapper baseStakeExtendInfoMapper;

    @Autowired
    private BaseUserService baseUserService;

    @Override
    public List<BaseStake> queryStake(BaseStakeCriteria criteria) {

        if (criteria==null){
            logger.info("分页查询桩集合条件不能为空!");
            return null;
        }

        List<BaseStake> stakes = baseStakeMapper.queryStake(criteria);

        return stakes;
    }

    @Override
    public int queryStakeCount(BaseStakeCriteria criteria) {
        if (criteria==null){
            logger.info("分页查询桩集合条件不能为空!");
            return 0;
        }

        int count = baseStakeMapper.queryStakeCount(criteria);

        return count;
    }

    @Override
    public int deleteStake(String uuid, BussinessTypeEnum.TRACE_TYPE trace_type,String sourceuuid) {
        if (uuid==null || uuid.trim().length()==0){
            logger.info("删除桩数据时候，桩主键为空，删除失败!");
            return 0;
        }

        BaseStake info = findStakeById(uuid);

        if (info==null){
            logger.info("需要删除的桩不存在，桩主键："+uuid);
            return 0;
        }

        int res = baseStakeMapper.deleteStake(uuid);

        if(res>=1){
            baseStakeRedisService.deleteStakeInfo(uuid);//根据uuid删除缓存中的数据
            sendStakeMQ(null,info,"delete");
            //操作轨迹
            baseAssetOperationTrajectoryService.addTraceLog(info.getUuid(),"DELETE",BussinessTypeEnum.TRACE_BUSINESS_TYPE.STAKE,trace_type,sourceuuid,null,info);
            //桩删除操作日志
            baseSystemOperationLogService.addSystemOperationLog(BussinessTypeEnum.WEB_OPERATOR_TYPE.STAKE, BussinessTypeEnum.TAG_TYPE.UPDATE,info.getUuid(),"",true);
        }
        return res;
    }

    @Override
    public BaseStake findStakeById(String uuid) {
        if (uuid==null || uuid.trim().length()==0){
            logger.info("桩查询主键为空，查询失败!");
            return null;
        }

        BaseStake stake = null;

        boolean existsStake = baseStakeRedisService.isExistsStake(uuid);//查找redis中是否存在数据
        if(existsStake){
            stake = baseStakeRedisService.getStakeInfoByUuid(uuid); //根据uuid从redis中获取桩数据
        }else {
            BaseStakeCriteria criteria = new BaseStakeCriteria();
            criteria.setUuid(uuid);
            stake = baseStakeMapper.getBaseStake(criteria);   //从数据库查找数据，并将结果缓存
            baseStakeRedisService.modifyStakenInfo(stake.getUuid(),stake);
        }

        return stake;
    }

    @Override
    public String saveStake(BaseStake info,BussinessTypeEnum.TRACE_TYPE typeEnum,String sourceuuid) {

        if (null == info) {
            throw new ServiceException(BasicDataStatus.PARAM_IS_EMPTY);
        }

        if (info.getUuid()==null || info.getUuid().trim().length()==0) {
            info.setUuid(UUIDTool.getUUID());
        }
        if (info.getStatus()==null) {
            info.setStatus(1000);
        }
        /*****begin Description:注释掉写入创建人,桩注册的时候已经写入了  author:zhangMumu edit 2018/4/14 0014 20:55*****/
//        BaseUser loginUser = this.baseUserService.getShiroUser(null);
//        info.setCreatoruuid(loginUser.getUuid());
        /*****end Description:注释掉写入创建人,桩注册的时候已经写入了  author:zhangMumu edit 2018/4/14 0014 20:55*****/

        int res = baseStakeMapper.insert(info);
        if(res>=1){
            boolean b = baseStakeRedisService.modifyStakenInfo(info.getUuid(),info);
            if (!b){
                logger.info("创建桩信息时，对应的桩redis数据创建失败!");
            }
            sendStakeMQ(info,null,"create");
            //操作轨迹
            baseAssetOperationTrajectoryService.addTraceLog(info.getUuid(),"CREATE",BussinessTypeEnum.TRACE_BUSINESS_TYPE.STAKE,typeEnum,sourceuuid,null,info);
            //桩添加操作日志
            baseSystemOperationLogService.addSystemOperationLog(BussinessTypeEnum.WEB_OPERATOR_TYPE.STAKE, BussinessTypeEnum.TAG_TYPE.ADD,info.getUuid(),"",true);
        }
        return info.getUuid();
    }

    @Override
    public int updateStakeModify(BaseStakeModifyBean modifyBean,BussinessTypeEnum.TRACE_TYPE typeEnum,String sourceid) {
        if(modifyBean==null){
            throw new ServiceException(BasicDataStatus.PARAM_IS_EMPTY);
        }
        BaseStake info = modifyBean.getBaseStake();
        if(info == null || StringUtils.isEmpty(info.getUuid())){
            throw new ServiceException(BasicDataStatus.STAKE_IS_EXISTS);
        }

        //修改桩信息
        try{
            updateStakeBySelective(info,typeEnum,sourceid);
        } catch (ServiceException se) {
            if(se.getStatus() != BasicDataStatus.STAKE_NOT_CHANGE){
                throw se;
            }
        }
        //修改桩扩展信息
        BaseStakeExtendInfo baseStakeExtendInfo = new BaseStakeExtendInfo();
        baseStakeExtendInfo.setStandard(modifyBean.getStandard());
        baseStakeExtendInfo.setProductiondate(modifyBean.getProductionDate());
        baseStakeExtendInfo.setUpdatedat(new Date());
        baseStakeExtendInfo.setUpdateruuid(this.baseUserService.getShiroUserUuid());
        baseStakeExtendInfo.setStakeno(info.getStakeno());
        List<BaseStakeExtendInfo> list = this.baseStakeExtendInfoMapper.qryStakeExtendInfoBySnakeNo(info.getStakeno());
        if(list.size() > 0) {
            this.baseStakeExtendInfoMapper.updateStakeExtendsByStakeNo(baseStakeExtendInfo);
        }else {
            baseStakeExtendInfo.setUuid(UUIDTool.getUUID());
            baseStakeExtendInfo.setCreatedat(new Date());
            baseStakeExtendInfo.setCreatoruuid(baseStakeExtendInfo.getUpdateruuid());
            this.baseStakeExtendInfoMapper.insert(baseStakeExtendInfo);
        }

        //修改枪信息
        List<BaseChargerModifyBean> chargers = modifyBean.getChargers();//获取枪列表

        //由原来updateBaseStake方法修改为updateByPrimaryKeySelective方法 zhangYiHang bigin 2018.4.9
        for (int i=0;i< chargers.size();i++){
            BaseChargerModifyBean modifyCharger = chargers.get(i);
            //新增停车位信息
            BaseParkingSpace parkingSpace = modifyCharger.getParkingSpace();
            BaseCharger charger = modifyCharger.getCharger();
            /*****begin Description:删除charger.getParkingSpaceUuid的判空  author:zhangMumu  2018/4/15 0015 18:03*****/
            if(charger == null){
            /*****end Description:删除charger.getParkingSpaceUuid的判空  author:zhangMumu  2018/4/15 0015 18:03*****/
                throw new ServiceException(BasicDataStatus.PARAM_IS_EMPTY);
            }
            if(parkingSpace != null){
                parkingSpace.setUuid(charger.getSpaceuuid());
                parkingSpace.setStationuuid(info.getStationuuid());
                parkingSpace.setParkingareauuid(info.getParkingareauuid());
                // 修改或新增停车位
                parkingSpace = baseParkingSpaceService.savePrakSpace(parkingSpace);

                charger.setSpaceuuid(parkingSpace.getUuid());
            }

            charger.setStakeUuid(info.getUuid());// 桩主键
            charger.setStakeNo(info.getStakeno());// 桩编号
            charger.setStationUuid(info.getStationuuid()); // 站主键
            charger.setParkingAreaUuid(info.getParkingareauuid()); // 停车区主键

            if(StringUtils.isEmpty(charger.getUuid())){

                //todo 表示新增枪，自动生成编码,需要调整为从缓存中获取
                if (StringUtils.isEmpty(charger.getAssetNo())) {
                    charger.setAssetNo(charger.getStakeNo() + "00"+i);
                    charger.setOutchargerno(charger.getStakeNo() + "00"+i);
                }
                if (StringUtils.isEmpty(charger.getChargerno())) {
                    charger.setChargerno(""+i);
                }
                // 新增充电枪
                baseChargerService.insertCharger(charger);
            } else {
                // 修改充电枪
                baseChargerService.updateCharger(charger);
            }
        }

        //添加对应站状态的修改 zhangYiHang begin 2018.4.9
        BaseStation baseStation = baseStationService.findById(info.getStationuuid());
        //判断桩状态是否为投运,直接修改站为投运
        if(info.getStakestatus() != null){
            if(info.getStakestatus() == BasicDataRedisConstants.STATION_STATUS_OPERATION){
                baseStation.setStationstatus(info.getStakestatus());
            } else {
                //判断桩状态是否为非投运,获取站下除当前桩以外投运桩数目
                int count = this.baseStakeMapper.qryStationOnlineStakeNum(info.getUuid());
                if(count > 0){
                    baseStation.setStationstatus(BasicDataRedisConstants.STATION_STATUS_OPERATION);
                } else {
                    baseStation.setStationstatus(info.getStakestatus());
                }
            }

            //修改站信息
            try{
                this.baseStationService.updateBySelective(baseStation,typeEnum);
            } catch (ServiceException se) {
                if(se.getStatus() != BasicDataStatus.STATION_NOT_CHANGE){
                    throw se;
                }
            }
        }
        //end

        return 1;
    }

    @Override
    public int updateStakeBySelective(BaseStake info, BussinessTypeEnum.TRACE_TYPE sourcetype, String operatoruuid) {
        if (null == info) {
            throw new ServiceException(BasicDataStatus.PARAM_IS_EMPTY);
        }
        BaseStake oldStake = this.findById(info.getUuid());
        if(oldStake == null){
            throw new ServiceException(BasicDataStatus.STAKE_IS_EXISTS);
        }

        if(!mqService.checkObjectChange(oldStake,info)){
            throw new ServiceException(BasicDataStatus.STAKE_NOT_CHANGE);
        }
        info.setUpdatedat(new Date());
        info.setUpdateruuid(this.baseUserService.getShiroUserUuid());
        int res = baseStakeMapper.updateByPrimaryKeySelective(info);
        if (res >= 1){

            boolean b = baseStakeRedisService.modifyStakenInfo(info.getUuid(),info);
            if (!b){
                logger.info("更新桩信息时，对应的桩redis数据更新失败!");
            }
            sendStakeMQ(info,oldStake,"update");
            //操作轨迹
            baseAssetOperationTrajectoryService.addTraceLog(info.getUuid(),"UPDATE",BussinessTypeEnum.TRACE_BUSINESS_TYPE.STAKE,sourcetype,operatoruuid,oldStake,info);
            //桩删除操作日志
            baseSystemOperationLogService.addSystemOperationLog(BussinessTypeEnum.WEB_OPERATOR_TYPE.STAKE, BussinessTypeEnum.TAG_TYPE.UPDATE,info.getUuid(),"",true);
        }
        return res;
    }

    /**
     * 根据装编号查找桩数据
     * @param stakeNo
     * @return
     */
    @Override
    public BaseStake getBaseStakeByStakeNo(String stakeNo) {

        BaseStake baseStake = null;

        String stakeuuid = baseStakeRedisService.getStakeInfoByNo(stakeNo);//根据桩编号查找桩主键
        if (stakeuuid!=null){
            baseStake = baseStakeRedisService.getStakeInfoByUuid(stakeuuid);//根据桩主键从缓存查找桩数据
        }

        if (baseStake==null) {
            BaseStakeCriteria stakeCriteria = new BaseStakeCriteria();
            stakeCriteria.setStakeno(stakeNo);
            baseStake = getBaseStakeByParams(stakeCriteria);//根据桩编号从数据库查找

            baseStakeRedisService.modifyStakenInfo(baseStake.getUuid(),baseStake);// 从数据库查询出的数据再添加到缓存中
        }

        return null;
    }

    /**
     * 根据注册码查找桩数据
     * @param reguuid
     * @return
     */
    @Override
    public BaseStake getBaseStakeByRegistration(String reguuid) {

        BaseStake baseStake = null;

        String stakeuuid = baseStakeRedisService.getStakeByReg(reguuid);
        if (stakeuuid!=null){
            baseStake = baseStakeRedisService.getStakeInfoByUuid(stakeuuid);
        }

        if (baseStake==null) {
            BaseStakeCriteria stakeCriteria = new BaseStakeCriteria();
            stakeCriteria.setRegistrationuuid(reguuid);//根据注册码主键查找
            baseStake = getBaseStakeByParams(stakeCriteria);
            if (baseStake!=null) {
                baseStakeRedisService.modifyStakenInfo(baseStake.getUuid(), baseStake);// 从数据库查询出的数据再添加到缓存中
            }
        }

        return baseStake;
    }

    @Override
    public String getAuthCodeByRegUuid(String reguuid) {

        if (reguuid==null || reguuid.trim().length()==0){
            return null;
        }

        String authCode = baseStakeRedisService.getAuthCodeByReg(reguuid);
        if (authCode==null || authCode.trim().length()==0){
            BaseStake baseStake = this.getBaseStakeByRegistration(reguuid);
            authCode = baseStake.getAuthcode();
        }

        return authCode;
    }

    @Override
    public BaseStake getBaseStakeByParams(BaseStakeCriteria criteria) {
        // TODO 需要缓存
        List<BaseStake> stakes = baseStakeMapper.queryStakeByParams(criteria);
        BaseStake stake = (stakes!=null && stakes.size()>0)?stakes.get(0):null;
        return stake;
    }

    @Override
    public BaseStake getStakeByStakeNo(String stakeNo) {

        BaseStake stake = null;
        String uuid = baseStakeRedisService.getStakeInfoByNo(stakeNo);
        if (uuid!=null && uuid.trim().length()>0){// 如果主键存在，则根据主键查询记录，否则查询数据库
            stake = baseStakeRedisService.getStakeInfoByUuid(uuid);
        }
        if(stake!=null){
            return stake;
        }else {
            BaseStakeCriteria criteria = new BaseStakeCriteria();
            criteria.setStakeno(stakeNo);
            List<BaseStake> stakes = baseStakeMapper.queryStakeByParams(criteria);
            stake = (stakes != null && stakes.size() > 0) ? stakes.get(0) : null;
        }

        return stake;
    }

    @Override
    public List<Stake> queryStakeHSF(BaseStakeCriteria criteria) {
        List<Stake> stakes = baseStakeMapper.queryStakeHSF(criteria);
        return stakes;
    }

    @Override
    public String getStakeNoByOrgCode(String orgCode) {
        String stakeNo = baseStakeMapper.getStakeNoByOrgCode(orgCode);
        return stakeNo;
    }

    @Override
    public Stake getStakeHSF(String stakeNo) {
        if (stakeNo==null){
            logger.info("HSF接口，根据桩编号查找桩，桩编号不能为空!");
            return null;
        }

        Stake stake = null;
        String uuid = baseStakeRedisService.getStakeUuidByNoHSF(stakeNo);// 从缓存读取桩主键
        if (uuid!=null){
            stake = baseStakeRedisService.getStakeInfoByUuidHSF(uuid);// 根据主键从缓存查找桩对象
        }

        if (stake==null) {
            BaseStakeCriteria criteria = new BaseStakeCriteria();
            criteria.setStakeno(stakeNo);
            List<Stake> stakes = baseStakeMapper.queryStakeHSF(criteria);

            stake = (stakes != null && stakes.size() > 0) ? stakes.get(0) : null;
            if (stake!=null) {
                baseStakeRedisService.modifyStakeInfoHSF(stake.getUuid(),stake);// 将桩信息添加到缓存
            }
        }
        return stake;
    }

    @Override
    public Stake getStakeHSF(BaseStakeCriteria criteria) {

        if (criteria==null){
            return null;
        }

        Stake stake = null;

        boolean existsStakeHSF = baseStakeRedisService.isExistsStakeHSF(criteria.getUuid());//查找缓存中是否存在
        if (existsStakeHSF){
            stake = baseStakeRedisService.getStakeInfoByUuidHSF(criteria.getUuid()); //从缓存中获取数据
        }else{
            List<Stake> stakes = baseStakeMapper.queryStakeHSF(criteria);//从数据库获取数据
            stake = (stakes!=null && stakes.size()==1)?stakes.get(0):null;
            if (stake!=null){
                baseStakeRedisService.modifyStakeInfoHSF(stake.getUuid(),stake);//将结果缓存
            }
        }
        return stake;
    }

    @Override
    public int queryStakeCountHSF(BaseStakeCriteria criteria) {
        int res = baseStakeMapper.queryStakeCountHSF(criteria);
        return res;
    }

    @Override
    public List<BaseStakeServiceBean> listServiceStake(BaseStakeCriteria criteria) {
        return baseStakeMapper.qryStakeServiceInfoDetail(criteria);
    }

    @Override
    public GlobalMonitor qryStakeGlobalMonitorToHSF(Map<String, Object> map) {
        GlobalMonitor globalMonitor = this.baseStakeMapper.qryStakeGlobalMonitorToHSF(map);
        logger.info("统计国网/三方桩数据,数据查询完成");
        return globalMonitor;
    }

    @Override
    public RegionStatistic qryStakeRegionStatisticToHSF(Map<String, Object> map) {
        RegionStatistic regionStatistic = this.baseStakeMapper.qryStakeRegionStatisticToHSF(map);
        logger.info("统计桩数据查询完成");
        return regionStatistic;
    }

    @Override
    public SocialPile qryBaseStakeCount(Map<String, Object> map) {
        return this.baseStakeMapper.qryBaseStakeCntToHsf(map);
    }

    @Override
    public List<EChartsData> qryEChartsData(Map<String, Object> map) {
        return this.baseStakeMapper.qryEChartsData(map);
    }

    @Override
    public List<BaseStake> qryBaseStakeList(Map<String, Object> map) {
        return this.baseStakeMapper.qryBaseStakeList(map);
    }



    @Override
    public BaseStake selectOne(BaseStake baseStake) {
        return this.baseStakeMapper.selectOne(baseStake);
    }

    @Override
    public BaseStakeServiceBean stakeDetail(String id) {
        return this.baseStakeMapper.stakeDetail(id);
    }

    @Override
    public int qryStakeCountByEquipmentUuid(String equipmentUuid) {
        BaseStake baseStake = new BaseStake();
        baseStake.setEquipmodeluuid(equipmentUuid);
        baseStake.setStatus(Integer.valueOf(DatabaseServiceStatus.SERVICE_NORMAL_STATUS.getCode()));
        return this.baseStakeMapper.selectCount(baseStake);
    }


    /**
     * 发送桩MQ
     * @param newStake
     * @param oldStake
     * @param tag
     * @return
     */
    public boolean sendStakeMQ(BaseStake newStake,BaseStake oldStake,String tag){
        if (newStake == null && oldStake != null && "delete".equalsIgnoreCase(tag)) {
            mqService.sendMessage("STAKE_OPERATING","DELETE",oldStake.getUuid(),oldStake.getStakeno(), BussinessTypeEnum.MQ_BUSINESS_TYPE.STAKE);
            return true;
        } else if (newStake != null && oldStake == null && "create".equalsIgnoreCase(tag)){
            mqService.sendMessage("STAKE_OPERATING","CREATE",newStake.getUuid(),newStake.getStakeno(),BussinessTypeEnum.MQ_BUSINESS_TYPE.STAKE);
            return true;
        } else if (newStake != null && oldStake != null && "update".equalsIgnoreCase(tag)){
            //根据配置的属性判断是否需要发送MQ
            if(mqService.needSendMQ(oldStake,newStake,"1000000002")){
                mqService.sendMessage("STAKE_OPERATING","UPDATE",newStake.getUuid(),newStake.getStakeno(),BussinessTypeEnum.MQ_BUSINESS_TYPE.STAKE);
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
}
